from django.shortcuts import render,redirect
#导包
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
#导入类视图
from django.views import View

import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
#导入加密库
import hashlib
#导入图片库
#绘画库
from PIL import ImageDraw
#字体库
from PIL import ImageFont
#图片库
from PIL import Image
#随机库
import random
#文件流
import io

import requests

#导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

#导入原生sql模块
from django.db import connection

import jwt

#导入redis数据库
import redis

#导入时间模块
import time

#导入公共目录变量
from mydjango.settings import BASE_DIR

#导包
from django.db.models import Q,F

#导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

from myapp.models import User, Goods, Cate, Comment, UserFlow
#导入序列化对象
from myapp.myser import UserSer, GoodsSer, CommentSer

#定义地址和端口
host = '127.0.0.1'
port = 6379

#建立redis连接
r = redis.Redis(host=host,port=port)

# 导入pymongo
import pymongo

# 建立mongo的链接对象
mongo_client = pymongo.MongoClient(host='localhost', port=27017)

# 导入bson
from bson import json_util as jsonb

# 商品检索接口
class GoodsSearch(APIView):
    def get(self, request):
        # 接收参数
        word = request.GET.get('word', None)
        # 检索 模糊匹配 name__contains 区分大小写 name__icontains 大小写不敏感  管道 | 代表 or  &/, 代表 并且
        # goodslist = Goods.objects.filter(name__icontains=word)

        # 翻译SQL select * from goods where (name like '%word%' or desc like '%word%')
        goodslist = Goods.objects.filter(Q(name__icontains=word) | Q(desc__icontains=word))

        # 序列化
        goods_ser = GoodsSer(goodslist, many=True)

        return Response(goods_ser.data)


# 工具方法，获取前n名的数据
def get_top_n(num):
    # 获取redis数据 切片
    goods_click = r.zrange('good_rank', 0, -1, desc=True, withscores=True)[:num]

    # 获取MySQL数据 聚合
    goods = Goods.objects.in_bulk([int(item[0]) for item in goods_click])

    # 合并操作
    res = []
    for item in goods_click:
        # 遍历列表
        # 捕获异常，防止MySQL和redis数据不同步问题
        try:
            res.append({int(item[1]): goods[int(item[0])]})

        except Exception as e:
            pass

    print(res)

    return res

# 商品排行榜数据视图
class GoodRank(APIView):
    def get(self, request):
        # 获取排名前n的数据
        get_res = get_top_n(10)

        res = []

        # 遍历进行序列化 双重遍历
        for dic in get_res:
            for k, v in dic.items():
                # 序列化
                data = GoodsSer(v).data
                # 将商品点击数附加到商品序列化数据中
                data['clicks'] = k
                res.append(data)

        # 返回
        return Response(res)

# 新的商品参与排名
class GoodsClick(APIView):
    def get(self, request):
        # 接收参数
        id = request.GET.get('id', None)
        # 修改商品点击数
        r.zincrby('good_rank', 1, int(id))

        # print(r.zrange('good_rank', 0, -1, desc=True, withscores=True))
        get_top_n(10)

        return Response({'message': '访问加1'})

# 对结果集美化方法
def dictfetchall(cursor):
    # 获取游标描述
    desc = cursor.description

    return [
        dict(zip([col[0] for col in desc], row))
        for row in cursor.fetchall()
    ]

# 商品关注接口(查询用户关注过的商品列表)
class UidFlow(View):
    def get(self, request):
        uid = request.GET.get('uid', None)

        # 建立游标对象
        cursor = connection.cursor()

        # 执行sql语句
        cursor.execute('select a.id, a.name, a.create_time from goods a left join userflow b on a.id = b.gid where b.uid = %s' % str(uid))

        # 获取结果
        # result = cursor.fetchall()
        result = dictfetchall(cursor)

        # 返回结果 手动序列化 indent缩进 空格 ensure_ascii 防止中文转码  content_type 声明头部
        return HttpResponse(json.dumps(result, ensure_ascii=False, indent=4, default=str), content_type='application/json')

# 关注商品接口(取消关注)
class GetFlow(APIView):
    def get(self, request):
        # 接收参数
        id = request.GET.get('id', None)
        uid = request.GET.get('uid', None)
        type = request.GET.get('type', 1)

        if int(type) == 1:
            # 关注
            userflow = UserFlow(gid=int(id), uid=int(uid))
            try:
                userflow.save()
                message = '关注成功'
                goods = Goods.objects.filter(id=int(id)).first()
                goods.flow = goods.flow + 1

            except Exception as e:
                print(str(e))
                message = '不能重复关注'
                pass
            
        elif int(type) == 0:
            UserFlow.objects.filter(gid=int(id), uid=int(uid)).delete()
            message = '已取关'
            goods = Goods.objects.filter(id=int(id)).first()
            goods.flow = goods.flow - 1
            goods.save()

        else:
            # 批量取关
            ids = request.GET.get('ids', None)
            # 批量操作 gid__in([2,4,5,6])
            UserFlow.objects.filter(uid=int(uid)).delete()

            # 强转
            id_list = eval(ids)

            # 只有用户收藏的商品才会显示在个人中心
            # 只可能存在批量删除不存在批量存储
            for id in id_list:
                userflow = UserFlow(gid=int(id), uid=int(uid))
                userflow.save()

                message = '批量操作成功'
        
        return Response({'message': message})

# 用户列表
class UserList(APIView):
    def get(self, request):
        # 查询
        user = User.objects.filter()
        # 序列化
        user_ser = UserSer(user, many=True)

        return Response(user_ser.data)

# 评论列表
class CommentList(APIView):
    def get(self, request):
        # 商品id
        id = request.GET.get('id', None)

        # 查询评论
        comment = Comment.objects.filter(gid=int(id)).order_by('-id')

        # 序列化
        comment_ser = CommentSer(comment, many=True)

        return Response(comment_ser.data)

# 反序列化入库商品评论  反序列化 json.loads  序列化 json.dumps
class InsertComment(APIView):
    def post(self, request):
        # 初始化参数
        # print(request.data)

        uid = request.POST.get('uid', None)

        if r.get(str(uid)):
            return Response({'code': 403, 'message': '评论太快了！等会再来'})

        comment = CommentSer(data=request.data)
        # 数据校验
        if comment.is_valid():
            # 数据入库
            # comment.create(comment.data)
            comment.save()

            # 插入评论标记
            r.set(str(uid), 'xing')
            r.expire(str(uid), 30)

        return Response({'code': 200, 'message': '评论成功'})

# 统计在线人数
class GetOnLine(APIView):
    def get(self, request):
        # 获取客户ip
        if 'HTTP_X_FORWARDED_FOR' in request.META:
            ip = request.META.get('HTTP_X_FORWARDED_FOR')

        else:
            ip = request.META.get('REMOTE_ADDR')

        # 对用户ip进行存储
        r.sadd('online', ip)

        # 设置超时时间 超时时长单位：秒
        r.expire('online', 20)

        # 获取在线人数数量
        myset = r.smembers('online')

        # 返回数据
        return Response({'online': len(myset)})


# 获取商品标签
class GetTags(View):
    def get(self, request):
        id = request.GET.get('id', None)

        # 建立数据库对象
        db = mongo_client.md
        # 建立表对象
        table = db.mytag
        # 查询数据
        res = table.find_one({"gid": str(id)})

        return HttpResponse(jsonb.dumps(res, ensure_ascii=False))

# 商品标签添加接口
class InsertTags(APIView):
    def get(self, request):
        id = request.GET.get('id', None)
        tags = request.GET.get('tags', None)
        tags = tags.split(',')

        # 建立数据库对象
        db = mongo_client.md
        # 建立表对象
        table = db.mytag

        # 排重操作
        # 查询
        res = table.find({'gid': str(id)}).count()

        if res > 0:
            return Response({'message': '已经存在数据'})

        else:
            # 入库操作
            table.insert({'gid': str(id), 'tags': tags})
            return Response({'message': '入库成功'})

        return Response({'message': 'test'})


# 商品信息接口
class GoodInfo(APIView):
    def get(self, request):
        id = int(request.GET.get('id', 0))

        # 查询数据
        good = Goods.objects.get(id=id)

        # 序列化操作
        good_ser = GoodsSer(good)

        return Response(good_ser.data)

# 商品列表页
class GoodsList(APIView):
    def get(self, request):
        # 当前页
        page = int(request.GET.get('page', 1))
        # 一页有多少个
        size = int(request.GET.get('size', 1))

        # 定义从哪开始切
        data_start = (page - 1) * size

        # 定义切到哪
        data_end = page * size

        # 查询数据
        goodslist = Goods.objects.all()[data_start: data_end]

        # 查询总数量
        count = Goods.objects.count()

        # 序列化操作
        goods_ser = GoodsSer(goodslist, many=True)

        res = {}
        res['code'] = count
        res['data'] = goods_ser.data
        return Response(res)

# 商品入库接口
class InsertGoods(APIView):

    def get(self,request):
        # 接收参数
        name = request.GET.get('name', 'null')
        desc = request.GET.get('desc', 'null')
        parms = request.GET.get('parms', 'null')
        img = request.GET.get('img', 'null')
        video = request.GET.get('video', 'null')
        price = request.GET.get('price', 'null')
        cate_id = request.GET.get('cate_id', 'null')
        

        # 排重
        goods = Goods.objects.filter(name=name).first()

        if goods:
            res = {}
            res['code'] = 405
            res['message'] = '该商品已经存在'
            return Response(res)

        # 进行入库
        goods = Goods(name=name, desc=desc, parms=parms, img=img, video=video, price=price, cate_id=cate_id)
        goods.save()

        # 查询商品id
        goods = Goods.objects.filter(name=name).first()

        res = {}
        res['code'] = 200
        res['id'] = goods.id
        res['message'] = '商品添加成功'

        return Response(res)

# 更新商品接口
class UpdateGoods(APIView):

    def get(self,request):
        # 接收参数
        name = request.GET.get('name', 'null')
        desc = request.GET.get('desc', 'null')
        parms = request.GET.get('parms', 'null')
        img = request.GET.get('img', 'null')
        video = request.GET.get('video', 'null')
        price = request.GET.get('price', 'null')
        cate_id = request.GET.get('cate_id', 'null')
        id = request.GET.get('id', 'null')


        # 查询商品id
        goods = Goods.objects.filter(id=int(id)).first()

        # 修改属性
        goods.name = name
        goods.desc = desc
        goods.parms = parms
        goods.img = img
        goods.video = video
        goods.price = int(price)
        goods.cate_id = int(cate_id)
        goods.save()


        res = {}
        res['code'] = 200
        res['id'] = goods.id
        res['message'] = '商品修改成功'

        return Response(res)
